package com.lqian.demo01;

import com.lqian.utils.SleepHelper;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 线程状态 6种
 */
public class ThreadState {
    public static void main(String[] args) throws Exception{
        Thread t1 =  new Thread(()->{
            System.out.println("2: "+ Thread.currentThread().getState());
            for (int i = 0; i <3 ; i++) {
                SleepHelper.sleepSeconds(1);
                System.out.print(i +" ");
            }
            System.out.println();
        });
        System.out.println("1: "+t1.getState());
        t1.start();
        t1.join();//Waits for this thread to die.
        System.out.println("3: "+t1.getState());
        //===============================================================
        Thread t2 = new Thread(()->{
            try {
                //让当前线程阻塞住，等着被别人叫醒
                LockSupport.park();
                System.out.println("t2 go to");
                //执行的时候 睡5秒 结束
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        t2.start();
        //主线程 睡一秒钟之后 保证让t2启动执行起来
        TimeUnit.SECONDS.sleep(1);
        // WAITING 没传时间
        System.out.println("4 "+t2.getState());

        LockSupport.unpark(t2);//叫醒t2
        TimeUnit.SECONDS.sleep(1);//主线程睡1秒 确保t2被叫醒
        //TIMED_WAITING 传了时间 因为t2被叫醒之后 又睡了5秒
        System.out.println("5 "+t2.getState());
        //===============================================================
        //作为锁
        final Object o = new Object();
        Thread t3 = new Thread(() -> {
            // t3 它要执行 synchronized (o) 必须要先持有这个锁对象才可以
            synchronized (o){
                System.out.println("t3 得到了锁");
            }
        });
        // 这个线程先把这个锁锁死了 5秒
        new Thread(()->{
           synchronized (o){
               SleepHelper.sleepSeconds(5);
           }
        }).start();
        //主线程睡一秒 保证上面已经把o锁死了 5秒
        SleepHelper.sleepSeconds(1);

        t3.start(); //t3 启动 它会去申请这把锁 但它得到不这把锁 竞争不到
        SleepHelper.sleepSeconds(1);
        //因此状态就为 >>> BLOCKED
        System.out.println("6 "+t3.getState());
        //===============================================================
        //只有synchronized这样的代码 才会进入BLOCKED状态
        //JUC的锁 -->CAS实现 >>> 忙等待 >>>WAITING (不会进入BLOCKED状态)
        final Lock lock = new ReentrantLock();
        Thread t4 = new Thread(() -> {
            // 申请锁
            lock.lock(); //省略try finally
            System.out.println("t4 得到了锁");
            lock.unlock();
        });

        //t4 执行之前 先把这把锁持有抢来
        new Thread(()->{
            // 申请锁
            lock.lock();
            // 睡5秒
            SleepHelper.sleepSeconds(5);
            lock.unlock();
        }).start();

        SleepHelper.sleepSeconds(1);

        t4.start(); //t4 拿不到lock这把锁
        SleepHelper.sleepSeconds(1);
        // 7 WAITING
        System.out.println("7 "+t4.getState());
        //===============================================================
        // 只有synchronized这样的代码 才会进入BLOCKED状态
        // synchronized是需要通过操作系统的调度的
        // 其他的都是WAITING OR TIMED_WAITING
        Thread t5 = new Thread(()->{
           LockSupport.park();
        });

        t5.start();
        SleepHelper.sleepSeconds(1);
        System.out.println("8 "+t5.getState());
        LockSupport.unpark(t5);
    }
}
